package hu.plusone.eregister.service.dao;

import hu.plusone.eregister.dao.TherapistDao;
import hu.plusone.eregister.model.Therapist;
import hu.plusone.eregister.service.TherapistService;
import java.util.Collection;
import java.util.HashSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("therapistUserDetailsService")
@Scope("singleton")
public class TherapistServiceImpl implements TherapistService {

    public static final String AUTHORITY_USER = "ROLE_USER";
    public static final String AUTHORITY_ADMIN = "ROLE_ADMIN";
    private static final Logger LOGGER = LoggerFactory.getLogger(TherapistServiceImpl.class);
    private TherapistDao dao;
    private PasswordEncoder passwordEncoder;

    @Autowired
    public TherapistServiceImpl(TherapistDao dao, PasswordEncoder passwordEncoder) {
        this.dao = dao;
        this.passwordEncoder = passwordEncoder;
        init();
    }

    @Override
    public Therapist get(String id) {
        return dao.findOne(id);
    }

    @Override
    public Iterable<Therapist> getAll() {
        return dao.findAll();
    }

    @Override
    @Transactional
    public void save(Therapist model) {
        String pw = model.getPassword();
        if (pw == null || "".equals(pw.trim())) {
            Therapist oldEntity = get(model.getEmail());
            model.setPassword(oldEntity.getPassword());
        } else {
            model.setPassword(passwordEncoder.encode(model.getPassword()));
        }
        dao.save(model);
    }

    @Override
    @Transactional
    public void delete(String id) {
        dao.delete(id);
    }

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        LOGGER.debug("Try to find user: {}", email);
        Therapist therapist = get(email);
        if (therapist == null) {
            LOGGER.warn("User not found: {}", email);
            throw new UsernameNotFoundException(email);
        }
        Collection<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority(AUTHORITY_USER));
        if (therapist.isLeader()) {
            authorities.add(new SimpleGrantedAuthority(AUTHORITY_ADMIN));
        }

        LOGGER.debug("User found: {}", therapist);
        return new User(therapist.getEmail(), therapist.getPassword(), authorities);
    }

    @Deprecated
    @Transactional
    private void init() {
        LOGGER.debug("init therapistService...");
        String email = "admin@admin.com";
        if (null != get(email)) {
            return;
        }
        Therapist t = new Therapist();
        t.setEmail(email);
        t.setPassword("admin");
        t.setLeader(true);
        save(t);
        LOGGER.debug("therapistService init finished.");
    }
}
